要製作語音閱讀器,就要用到瀏覽器內建的SpeechSynthesis API。
const voicesDropdown = document.querySelector('[name="voice"]');
// 音調、速度 及 文字輸入框
const options = document.querySelectorAll('[type="range"], [name="text"]');
// 播放鍵
const speakButton = document.querySelector("#speak");
// 暫停鍵
const stopButton = document.querySelector("#stop");
const synth = window.speechSynthesis;
const voices = speechSynthesis.getVoices();
但在 Chrome 中這樣使用後並印出來,你會發現只有一個空陣列裡面什麼也沒有,那是因為 Chrome 語音合成功能需要時間來初始化和載入可用的語音選項。因此為了確保能正確提取語音包,我們要針對synthy
再添加一個針對voiceschanged
事件的監聽器,當語音完全載入後會觸發loadVoices
函式,並將語音選項渲染於列表中,改寫程式碼。
// 宣告語音包變數供後面更新
let voices;
// 初始載入頁面即執行(Safari瀏覽器
loadVoices();
// 語音包加載完畢再持行一次(Chrome瀏覽器
synth.addEventListener("voiceschanged", loadVoices);
function loadVoices() {
// 提取語音包
voices = synth.getVoices();
// 創建文檔片段
const fragment = document.createDocumentFragment();
// 篩選英文語音,並創建選項節點放入文檔片段裝
voices
.filter((voice) => voice.lang.includes("en"))
.forEach((voice) => {
const option = document.createElement("option");
option.value = voice.name;
option.textContent = `${voice.name} (${voice.lang})`;
fragment.appendChild(option);
});
// 渲染於畫面上<select>tag 中
voicesDropdown.appendChild(fragment);
}
msg
變數之中>。SpeechSynthesisUtterancem 擁有六種屬性分別為lang:語言
、pitch:音調
、rate:語速
、text:內容
、voice:語音包
、volume:聲音
。// 建構出一個語音訊息物件
const msg = new SpeechSynthesisUtterance();
// 統一設定為英文
msg.lang = "en-US";
// 切換播放語音
speakButton.addEventListener("click", toggle);
stopButton.addEventListener("click", () => toggle(false));
function toggle(startOver = true) {
// 播放前再次設定要唸的內容
msg.text = document.querySelector("textarea").value;
// 停止上一次唸到一半的語音合成器
synth.cancel();
if (startOver) synth.speak(msg);
}
// 調整速度及音調
options.forEach((option) => option.addEventListener("input", changeOptions));
// 調整語音包
voicesDropdown.addEventListener("change", setVoice);
function changeOptions(e) {
msg[this.name] = this.value;
}
function setVoice(e) {
msg.voice = voices.find((voice) => voice.name === this.value);
// 切換就執行播放,使用者體驗會較好
toggle();
}